/******************************************************************************
 * Copyright (C) 2014 ShenZhen YiHua Computer Co., Ltd.
 * All Rights Reserved.
 * 本软件为深圳怡化电脑股份有限公司开发研制。未经本公司正式书面同意，其他任何个人、团体
 * 不得使用、复制、修改或发布本软件.
 *****************************************************************************/
package net.dgg.dggcloud.core.fileload;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import net.dgg.dggcloud.core.util.ConfigLoader;

/**
 * 文件上传下载工具类
 *
 */
public final class FileLoadTool
{
    private static final Logger logger = Logger.getLogger(FileLoadTool.class);

    /**
     * 文件大小限制
     */
    private static int FILESIZE = 10 * 1024 * 1024;

    public static String BASE_DIR = System.getProperty("user.dir");

    /**
     * 支持的文件扩展名类型
     */
    public static String FILEEXTS = ConfigLoader.getConfigLoader().getVaule("attachment_ext");

    /**
     * 
     */
    
    public static String ATTACHMENT_TIME = ConfigLoader.getConfigLoader().getVaule("attachment_time");

    
    // 重新读配置文件进行初始化，界面也引用这几个常量
    static
    {
        if (ConfigLoader.getConfigLoader().getVaule("attachment_size") != null)
        {
            try
            {
                FILESIZE = Integer.parseInt(ConfigLoader.getConfigLoader().getVaule("attachment_size")) * 1024 * 1024;
            }
            catch (Exception ex)
            {
                logger.error("Config item:attachment_size in yhcloud.properties ", ex);
            }
        }
        else
        {
            logger.error("Config item:attachment_size not found in yhcloud.properties");
        }

        if (ConfigLoader.getConfigLoader().getVaule("attachment_path") != null)
        {
            BASE_DIR = ConfigLoader.getConfigLoader().getVaule("attachment_path").replace('\\', File.separatorChar);
        }
        else
        {
            logger.error("Config item:attachment_path not found in yhcloud.properties");
        }

        if (ConfigLoader.getConfigLoader().getVaule("attachment_ext") != null)
        {
            FILEEXTS = ConfigLoader.getConfigLoader().getVaule("attachment_ext");
        }
        else
        {
            logger.error("Config item:attachment_ext not found in yhcloud.properties");
        }
    }

    public static final int getSizeLimit()
    {
        return FILESIZE;
    }

    public static final String getExtLimit()
    {
        return FILEEXTS;
    }

    /**
     * 文件下载.<br/>
     *
     * @param request
     * @param response
     * @param fileDownload 文件下载接口
     * @return 文件下载成功返回true
     * @throws IOException
     */
    public static boolean fileDownload(HttpServletRequest request, HttpServletResponse response,
            IFileDownload fileDownload) throws IOException
    {
        // 需要下载的文件
        File file = fileDownload.prepareDownloadFile(request);

        RandomAccessFile raf = null;
        byte[] fileStream = null;
        boolean success = false;
        try
        {
            raf = new RandomAccessFile(file, "r"); // 只读
            fileStream = new byte[(int) raf.length()];
            raf.readFully(fileStream); // 一次性读取
            success = true;
        }
        finally
        {
            if (raf != null)
            {
                raf.close();
            }
        }

        if (success)
        {
            String fileName = file.getName();
            // 以流的形式下载文件
            response.setContentType("application/octet-stream; charset=UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\""
                    + new String(fileName.getBytes("GBK"), "ISO8859-1") + "\"");
            OutputStream toClient = null;
            try
            {
                toClient = new BufferedOutputStream(response.getOutputStream());
                toClient.write(fileStream); // 一次性返回下载
                toClient.flush();
            }
            finally
            {
                if (toClient != null)
                {
                    toClient.close();
                }
            }
        }

        return success;
    }

    /**
     * 文件上传 一次性批量保存
     * 
     * @param request
     * @param fileUpload 文件上传接口
     * @throws IOException
     */
    public static String multiUpload(HttpServletRequest request, IFileUpload fileUpload, StringBuilder result)
            throws IOException
    {
        // 创建一个通用的多部分解析器
        CommonsMultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        // 判断 request 是否有文件上传,即多部分请求
        if (resolver.isMultipart(request))
        {
            // 源单号
            String sourceId = request.getParameter("sourceId");
            String moduleType = request.getParameter("moduleType");
            String systemType = request.getParameter("systemType");
            String funcType = request.getParameter("funcType");
            String atType = request.getParameter("atType");
            
            
            String atCategory = request.getParameter("atCategory");
            if (sourceId == null || sourceId.isEmpty() || systemType == null || systemType.isEmpty()
                    || moduleType == null || moduleType.isEmpty())
            {
                return "请求参数不正确";
            }

            // 转换成多部分request
            MultipartHttpServletRequest multiRequest = resolver.resolveMultipart(request);
            // 取得request中的所有file域名
            Iterator<String> fieldItr = multiRequest.getFileNames();
            // 调用接口对上传文件进行过滤
            if ((fieldItr == null) || (!fieldItr.hasNext()))
            {
                return "没有选择文件";
            }
            Map<String, FileInfoModel> fileMap = new HashMap<String, FileInfoModel>();
            while (fieldItr.hasNext())
            {
                // 取得上传文件
                String fieldName = fieldItr.next();
                MultipartFile file = multiRequest.getFile(fieldName);
                FileInfoModel fileInfoModel = resolveFile(file, fileUpload, sourceId, systemType, moduleType, funcType,
                        atType, null,atCategory);
                if (fileInfoModel == null)
                {
                    continue;
                }
                
                if (  fileInfoModel.getError() != null )
                {   
                    return   fileInfoModel.getError();
                }

                if (fileInfoModel.isInValid())
                {
                    logger.error(fileInfoModel.getError() + "\n" + fileInfoModel);
                    continue;
                }

                // 每个文件标签对应一个附件类型atType0~~atType1.2.3.4.5...
                String atTypex = multiRequest.getParameter("atType" + fieldName.substring(4));
                result.append(fieldName.substring(4)).append(',');
                if (atTypex != null)
                {
                    fileInfoModel.setFileType(atTypex);
                }
                // 文件保存成功后记录路径信息
                fileMap.put(fileInfoModel.getName(), fileInfoModel);
            }
            
            
           

            if (fileMap.isEmpty())
            {
                return "没有附件上传成功";
            }
            else
            {
                // 至少有一个文件上传
                try
                {
                    fileUpload.saveFileInfo(fileMap);
                    result.delete(result.length() - 1, result.length());
                }
                catch (Exception e)
                {
                    result.delete(0, result.length());
                }
                return null;
            }
        }
        else
        {
            // 请求中没有文件Multi
            return "请求信息不正确";
        }
    }

    /**
     * @param file 请求文件对象
     * @param fileUpload 文件操作借口
     * @param sourceId 源单号
     * @param systemType 系统类型
     * @param moduleType 模块类型
     * @param funcType 功能类型
     * @param fileType 附件类型
     * @param filePath 附件路径
     * @return FileInfoModel
     */
    public static FileInfoModel resolveFile(MultipartFile file, IFileUpload fileUpload, String sourceId,
            String systemType, String moduleType, String funcType, String fileType, String filePath,String category)
    {
        if (file == null)
        {
            // 文件对象为空则忽略
            return null;
        }

        // 取得当前上传文件的文件名称
        String originalFilename = file.getOriginalFilename();
        // 如果名称不为“”,说明该文件存在，否则说明该文件不存在
        if (originalFilename.trim().isEmpty())
        {
            // 文件对象为空不上传
            return null;
        }
        // 多校验了一次
        FileInfoModel fileInfoModel = new FileInfoModel();
        if (FILESIZE < file.getSize())
        {
            // 文件太大设置错误信息返回
            fileInfoModel.setError("上传的文件大于规定上限！");
            
            return fileInfoModel;
        }

        fileInfoModel.setOriginalFilename(originalFilename);
        int index = originalFilename.indexOf("/");
        if (index < 0)
        {
            index = originalFilename.indexOf("\\");
        }
        if (index < 0)
        {
            fileInfoModel.setName(originalFilename);
        }
        else
        {
            fileInfoModel.setName(originalFilename.substring(index + 1));
        }

        if (!fileUpload.resoveFileInfo(fileInfoModel))
        {
            // 文件扩展名不支持则忽略
            return fileInfoModel;
        }

        fileInfoModel.setModuleType(moduleType);
        fileInfoModel.setSystemType(systemType);
        fileInfoModel.setSourceId(sourceId);
        fileInfoModel.setFileType(fileType);
        fileInfoModel.setFuncType(funcType);
        fileInfoModel.setPath(filePath);
        
        fileInfoModel.setAtCategory(category);
      
        if (filePath == null)
        {
            fileUpload.checkFile(fileInfoModel);
        }

        File targetFile = getFile(fileInfoModel);
        logger.debug("上传文件：" + targetFile.getAbsolutePath());
        try
        {
            // 新检查并删除旧文件，再保存新文件
            if (targetFile.exists())
            {
                // 相当于替换已经存在的文件
                targetFile.delete();
            }
            targetFile.mkdirs();
            file.transferTo(targetFile);
        }
        catch (Exception e)
        {
            logger.error(e.getMessage(), e);
            fileInfoModel.setError("保存文件出错");
            return fileInfoModel;
        }

        return fileInfoModel;
    }

    public final static File getFile(FileInfoModel fileInfoModel)
    {
        final String separator = File.separator;

        if (fileInfoModel.getPath() == null || fileInfoModel.getPath().isEmpty())
        {
            if (fileInfoModel.getFuncType() == null)
            {
                fileInfoModel.setPath(BASE_DIR + separator + fileInfoModel.getSystemType() + separator
                        + fileInfoModel.getModuleType() + separator + fileInfoModel.getSourceId());
            }
            else
            {
                // 如果功能类型非空，则将功能类型作为文件路径的一部分
                fileInfoModel.setPath(BASE_DIR + separator + fileInfoModel.getSystemType() + separator
                        + fileInfoModel.getModuleType() + separator + fileInfoModel.getFuncType() + separator
                        + fileInfoModel.getSourceId());
            }
        }
        return new File(fileInfoModel.getPath(), returnFileAddHead(fileInfoModel.getAtCategory())+fileInfoModel.getName());
    }
    
    
    public final static String returnFileAddHead(Object ojb)
    {
        if( ojb != null)
        {
            String strValue= String.valueOf(ojb);
            if (!(("".equals(strValue))|| "null".equals(strValue)))
            {
                return strValue.trim()+"_";
                
            }
            
        }        
        return  "";
        
    }
    
    

    public final static File getFile(String baseDir, String fileName)
    {
        return new File(baseDir, fileName);
    }
}
